*! 2.2.2 NJC 15 Sep 2017                    
* 2.2.1 NJC 29 Mar 2010                    
* 2.2.0 NJC 18 Dec 2009                    
* 2.1.0 NJC 17 Aug 2005                    
* 2.0.2 NJC 12 Aug 2004                    
* 2.0.1 NJC 29 Sep 2003 tscale -> trscale
* 2.0.0 NJC 7 May 2003       
* 1.6.1 NJC 7 Apr 2003       
* 1.6.0 NJC 5 Dec 2002       
* 1.5.0 NJC 24 Mar 1999        [STB-51: gr41]
* 1.4.0 NJC 17 Mar 1998
* 1.0.0 NJC 5 Mar 1998
program distplot, sort 
	version 8.0

	* allobs undocumented 
	syntax varlist(numeric) [if] [in] [fweight aweight/] ///
	[ , BY(str asis) OVER(varname) FREQuency MIDpoint MISSing ///
	TRSCale(str) REVerse Reverse2(str) MSymbol(str)     ///
	ADDPLOT(str asis) PLOT(str asis) ALLOBS * ]
	
	tokenize `varlist'
	local nvars : word count `varlist'

	// error checks 
	if "`allobs'" != "" marksample touse, novarlist 
	else marksample touse  
	
	if "`missing'" == "" { 
		if "`over'" != "" markout `touse' `over', strok 
	}
	else if "`over'" == "" di as txt "missing only applies with over()" 
	
	if "`exp'" == "" local exp "1" 
	else {
		capture assert `exp' >= 0 if `touse'
		if _rc {
			di as err "weight assumes negative values"
			exit 402
	        }    
	}

	if "`over'" != "" {
		if `nvars' > 1 {
			di as err "too many variables specified"
			exit 103
	    	}
	}


	if `"`by'"' != "" { 
		gettoken by opts : by, parse(",") 
		local byby by(`by' `opts') 
		local bylabel : variable label `by' 
	}	
	
	qui count if `touse'
	if r(N) == 0 {
		di as err "no observations satisfy conditions"
		exit 2000
	}

	if "`trscale'" != "" { 
		if !index("`trscale'","@") { 
			di as err "trscale() does not contain @" 
			exit 198 
		}
	} 

	if "`frequency'" != "" & "`midpoint'" != "" { 
		di as err "frequency and midpoint may not be combined"
		exit 198 
	}

	if "`reverse2'" != "" { 
		if "`reverse2'" != "ge" {
			di as err "reverse() option invalid" 
			exit 198 
		} 	
		if "`midpoint'" != "" { 
			di as txt "(reverse midpoint options assumed)" 
			local reverse "reverse" 
		}
		else local ge "ge" 
	} 
	
	// we're in business 
	
	quietly {
		preserve
		keep if `touse'  
		tempvar wt id col P midP 
		gen double `wt' = `exp'

		if `nvars' > 1 { 
			gen long `id' = _n 
			tempname data datalbl 
			local i = 1 
			foreach v of var `varlist' {
				local lbl`i' : variable label `v' 
				if `"`lbl`i''"' == "" local lbl`i' "`v'" 
				rename `v' `data'`i++'
				local xlbl "`xlbl' `v'"
			} 
	        	reshape long `data', i(`id') j(`col') 
		    	forval i = 1 / `nvars' {
				label def `datalbl' `i' `"`lbl`i''"', modify
	    		}
			label val `col' `datalbl' 
		        local varlist "`data'"
			label var `varlist' "`xlbl'"
			if "`by'" != "" label var `by' `"`bylabel'"' 
			local over "`col'"
		}

		sort `touse' `by' `over' `varlist'
		local over1 "by `touse' `by' `over' :"
		local over2 "by `touse' `by' `over' `varlist' :"
		
		if "`midpoint'" == "" { 
			`over1' gen double `P' = sum(`wt') 
			if "`frequency'" == "" `over1' replace `P' = `P' / `P'[_N]
			if "`reverse'" != ""   `over1' replace `P' = `P'[_N] - `P'
		} 
		else {
			`over2' gen double `P' = sum(`wt') 
			`over2' replace `P' = `P'[_N] 
			`over2' keep if _n == _N 
			`over1' gen double `midP' = 0.5 * `P' + sum(`P'[_n-1]) 
			`over1' replace `P' = sum(`P') 
			`over1' replace `P' = `midP' / `P'[_N] 
			if "`reverse'" != "" replace `P' = 1 - `P' 
 		} 
		
		if "`ge'" != "" replace `varlist' = -`varlist' 
		local ylbl = cond("`xlbl'" != "", "value", "`varlist'") 
	
		if "`midpoint'" != ""  {
			local ytitle "Cumulative probability midpoint" 	
		}
		else if "`frequency'" == "" {
			local ytitle "Cumulative probability"
		}
		else local ytitle "Cumulative frequency" 
		
		if "`over'" != "" {
			tempvar group
			bysort `over' (`P') : gen byte `group' = _n == 1 
			replace `group' = sum(`group')
			local overlab : value label `over'
			local j = 1 
			forval i = 1 / `= `group'[_N]' {
				tempvar P_i`i'
		 		gen double `P_i`i'' = `P' if `group' == `i'
         		        local overval = `over'[`j']
		    		if "`overlab'" != "" { 
					local overval : label `overlab' `overval' 
				}
			        label var `P_i`i'' `"`overval'"'
				local Plist "`Plist' `P_i`i''"
				count if `group' == `i'
				local j = `j' + r(N)
			}
		}
		else { 
			local sort "sort" 
			_crcslbl `P' `varlist' 
			local Plist "`P'"
		}	

		if "`trscale'" != "" { 
			foreach v of var `Plist' { 
				local newv : subinstr local trscale "@" "`v'", all 
				replace `v' = `newv' 
			}
		} 
	} 	

	if "`msymbol'" == "" local msymbol "oh dh th sh smplus x O D T S + X"
	
	twoway line `Plist' `varlist', ytitle("`ytitle'") /// 
	`sort' ms(`msymbol') `byby' `options' ///
	|| `plot' /// 
	|| `addplot' /// 
	// blank 
end

